package pl.drypisy;

import java.awt.*;
import java.awt.image.BufferedImage;

/**
 * Created with IntelliJ IDEA.
 * User: Adam Syrek
 * Date: 11.01.13
 * Time: 01:10
 * To change this template use File | Settings | File Templates.
 */

public class SkewProcess extends ImageProcess {
    private BufferedImage src;
    private int width, height;
    private double xAngle, yAngle;
    private double wSkew=0, hSkew=0;
    private boolean processed = false;
    double xTangens, yTangens;

    public void setXAngle(double rad)
    {
        xAngle = rad;
    }

    public void setYAngle(double rad)
    {
        yAngle = rad;
    }

    @Override
    public BufferedImage process(BufferedImage img) {
        BufferedImage tmp = img;
        tmp = processX(tmp);
        tmp = processY(tmp);
        return tmp;
    }


    private BufferedImage processX(BufferedImage img)
    {
        this.src = img;
        srcWidth = src.getWidth();
        srcHeight = src.getHeight();

        xTangens = Math.tan(Math.toRadians(xAngle));
        yTangens = 0;

        width = (int)Math.ceil((double)srcWidth + Math.abs(xTangens*(double)srcHeight));
        height = (int)Math.ceil((double)srcHeight + Math.abs(yTangens*(double)width));

        BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

        int[] outPixels = new int[width] ;
        int[] inPixels = src.getRGB(0, 0, srcWidth, srcHeight, null, 0, srcWidth);
        double out[] = new double[2];
        int nw,ne,sw,se;
        for(int y=0; y<height-1; ++y)
        {
            for(int x=0; x<width-1; ++x)
            {
                getOriginalCoordinates(x,y,out);
                int srcX = (int)Math.floor( out[0] );
                int srcY = (int)Math.floor( out[1] );
                int pix;
                if(doInterpolation) {
                    double xWeight = out[0]-srcX;
                    double yWeight = out[1]-srcY;
                    nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight);
                    ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight );
                    sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight );
                    se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight );
                    pix = bilinearInterpolation(xWeight, yWeight,  nw, ne, sw, se);
                }
                else pix = getPixel(inPixels,srcX,srcY,srcWidth,srcHeight);
                outPixels[x] = pix;
            }
            dest.setRGB(0, y, width, 1, outPixels, 0, width);
        }

        return dest;
    }

    private BufferedImage processY(BufferedImage img)
    {
        this.src = img;
        srcWidth = src.getWidth();
        srcHeight = src.getHeight();

        xTangens = 0;
        yTangens = Math.tan(Math.toRadians(yAngle));

        width = (int)Math.ceil((double)srcWidth + Math.abs(xTangens*(double)srcHeight));
        height = (int)Math.ceil((double)srcHeight + Math.abs(yTangens*(double)width));

        BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

        int[] outPixels = new int[width] ;
        int[] inPixels = src.getRGB(0, 0, srcWidth, srcHeight, null, 0, srcWidth);
        double out[] = new double[2];
        int nw,ne,sw,se;
        for(int y=0; y<height-1; ++y)
        {
            for(int x=0; x<width-1; ++x)
            {
                getOriginalCoordinates(x,y,out);
                int srcX = (int)Math.floor( out[0] );
                int srcY = (int)Math.floor( out[1] );
                int pix;
                if(doInterpolation) {
                    double xWeight = out[0]-srcX;
                    double yWeight = out[1]-srcY;
                    nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight);
                    ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight );
                    sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight );
                    se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight );
                    pix = bilinearInterpolation(xWeight, yWeight,  nw, ne, sw, se);
                }
                else pix = getPixel(inPixels,srcX,srcY,srcWidth,srcHeight);
                outPixels[x] = pix;
            }
            dest.setRGB(0, y, width, 1, outPixels, 0, width);
        }

        return dest;
    }
    @Override
    protected void getOriginalCoordinates(int x, int y, double[] out) {

        //dziala dla angle >0, ucina y troche
        //troche duzo
        out[0] = x - xTangens*((y-yTangens*x)/(1 - xTangens*yTangens));
        out[1] = (y-yTangens*x)/(1-xTangens*yTangens);
        
        /*out[0] = (x-xTangens*y)/(1.0-xTangens*yTangens);
        //out[1] = y-yTangens*out[0];
        out[1] = (y-yTangens*x)/(1.0-xTangens*yTangens);*/
        if(xAngle < 0) out[0] = out[0] + (double)height*xTangens;
        if(yAngle < 0) out[1] = out[1] + (double)width*yTangens;

        //nie dziala, bo przesuwa obrazek -> za duza czesc po plusie
        //out[0] = x - (double)height*xTangens + y*Math.sin(Math.toRadians(xAngle));
        //out[1] = y - (double)width*yTangens + x*Math.sin(Math.toRadians(yAngle));

    }

}
